#ifndef _KERNEL_H_INCLUDED_
#define _KERNEL_H_INCLUDED_

#include "defines.h"
#include "syscall.h"
#include "kinfo.h"

// TCB (スレッド・コントロール・ブロック)
typedef struct _kz_thread {
    kz_thread_id_t id;
    int priority;
    char name[THREAD_NAME_SIZE + 1];
    char *stack;
    unsigned stacksize;
    uint16 flags;
#define THREAD_ALIVE        ((uint16)1 << 0)
#define THREAD_READY        ((uint16)1 << 1)
#define THREAD_WAITMSG      ((uint16)1 << 2)
#define THREAD_WAITALARM    ((uint16)1 << 3)
    struct _kz_thread *next;
    struct {
        uint32 sp;
    } context;
    struct {
        kz_func_t func;
        int argc;
        char *argv;
    } init;
    struct {
        kz_syscall_type_t type;
        kz_syscall_param_t *param;
    } syscall;
    struct {
        uint32 count;
        int index;
    } alarm;
} kz_thread;

extern kz_thread threads[];
extern int in_thread;
extern kz_thread *current;

void thread_wakeup(kz_thread *thp);

kz_thread_id_t sys_run(kz_func_t func, char *name, int priority, unsigned stacksize, int argc, char *argv);
int sys_wakeup(kz_thread_id_t id);
void *sys_kmalloc(int size);
int sys_kmfree(void *p);
int sys_send(kz_msgbox_id_t id, int size, char *p, int priority, int maxnum, kz_thread *sender);
kz_thread_id_t sys_recvi(kz_msgbox_id_t id, int *sizep, char **pp);
int sys_setintr(softvec_type_t type, kz_handler_t handler);
int sys_resetintr(softvec_type_t type);
kz_msgbox_id_t sys_getmsgbox(void);
int sys_freemsgbox(kz_msgbox_id_t id);
char *sys_getthreads(void);
char *sys_resource(void);
uint32 sys_systime(void);

// Memory
#define MEMORY_AREA_NUM 4
void kzmem_init(void);
void *kzmem_alloc(int size);
void kzmem_free(void *mem);
void resource_memory(kz_resourceinfo_t *infop);

// IPC
void ipc_init(void);
void resource_msgbox(kz_resourceinfo_t *infop);

kz_msgbox_id_t msgbox_get(void);
void msgbox_free(kz_msgbox_id_t id);

int pushmsg(kz_msgbox_id_t id, int size, char *p, int priority, int maxnum, kz_thread *sender);
kz_thread_id_t popmsg(kz_msgbox_id_t id, int priority, int *sizep, char **pp);
kz_thread_id_t recvmsg(kz_msgbox_id_t id, int priority, kz_thread *receiver);

int msg_arrived(kz_msgbox_id_t id);
void setreceiver(kz_msgbox_id_t mb, kz_thread *receiver);
kz_thread *getreceiver(kz_msgbox_id_t id);
void cancelreceiver(kz_msgbox_id_t id);
void sendreceiver(kz_msgbox_id_t id, kz_thread *sender, int size, char *p);

// Timer
uint32 get_systime(void);
void set_alarm(kz_thread *thp, uint32 tick);
void cancel_alarm(kz_thread *thp);
void timer_init(void);

#endif
